﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Drawing;
using System.IO;
using System.Drawing.Imaging;
using ZRLabs.Yael.BasicFilters;
using System.Drawing.Drawing2D;
namespace Lbb.Drawing
{
    public static class ImageHelper
    {
        /// <summary>
        /// 保存缩略图
        /// </summary>
        /// <param name="imagePath"></param>
        /// <param name="config"></param>
        public static void SaveThumbnail(string imagePath, ThumbnailConfig config = null)
        {
            if (config == null)
            {
                config = new ThumbnailConfig();
            }
            Image img = Image.FromFile(imagePath);
            Image resizedImage = ImageHelper.ResizeImage(img, config);
            img.Dispose();
            ImageHelper.SaveJpeg(imagePath, resizedImage, config.Quality);
        }
        /// <summary>
        /// Resize图片
        /// </summary>
        /// <param name="source"></param>
        /// <param name="config"></param>
        /// <returns></returns>
        public static Image ResizeImage(this Image source, ThumbnailConfig config)
        {
            return ResizeImage(source, config.Width, config.Height, config.BackgroundColor, config.ResizeStyle, config.MustFit);
        }
        /// <summary>
        /// Resize图片
        /// </summary>
        /// <param name="source"></param>
        /// <param name="width"></param>
        /// <param name="height"></param>
        /// <param name="backgroundColor"></param>
        /// <param name="style"></param>
        /// <param name="mustFit"></param>
        /// <returns></returns>
        public static Image ResizeImage(this Image source, int width, int height, Color? backgroundColor = null, ResizeStyle style = ResizeStyle.Zoom, bool mustFit = true)
        {
            ResizeFilter resize = new ResizeFilter();
            resize.BackGroundColor = backgroundColor ?? Color.Transparent;
            resize.InterpolationType = System.Drawing.Drawing2D.InterpolationMode.HighQualityBilinear;
            //double aspectRatio = width / height;

            switch (style)
            {
                case ResizeStyle.Zoom:
                    if (source.Height > source.Width)
                    {
                        resize.LockRatioByHeight = true;
                        resize.KeepAspectRatio = true;
                        resize.Height = height;
                    }
                    else if (source.Width > source.Height)
                    {
                        resize.LockRatioByWidth = true;
                        resize.KeepAspectRatio = true;
                        resize.Width = width;
                    }
                    else
                    {
                        resize.Height = height;
                        resize.Width = width;
                        resize.KeepAspectRatio = true;
                    }
                    source = resize.ExecuteFilter(source);
                    break;
                case ResizeStyle.Stretch:
                    resize.Height = height;
                    resize.Width = width;
                    resize.KeepAspectRatio = false;
                    source = resize.ExecuteFilter(source);
                    break;
                case ResizeStyle.Centre:
                    int cWidth = width;
                    int cHeight = height;
                    //居中裁剪
                    if (width > source.Width)
                    {
                        cWidth = source.Width;
                    }
                    if (height > source.Height)
                    {
                        cHeight = source.Height;
                    }
                    decimal resizePercent = 1;
                    int xPosition = 0;
                    int yPosition = 0;
                    if (source.Width > source.Height)
                    {
                        resizePercent = Convert.ToDecimal(cHeight) / Convert.ToDecimal(source.Height);
                        resize.Height = cHeight;
                        resize.Width = Convert.ToInt16(Convert.ToDecimal(source.Width) * resizePercent);
                        source = resize.ExecuteFilter(source);
                        xPosition = Convert.ToInt16((Convert.ToDecimal(resize.Width) - Convert.ToDecimal(cWidth)) / new Decimal(2));
                    }
                    else
                    {
                        resizePercent = Convert.ToDecimal(cWidth) / Convert.ToDecimal(source.Width);
                        resize.Width = cWidth;
                        resize.Height = Convert.ToInt16(Convert.ToDecimal(source.Height) * resizePercent);
                        source = resize.ExecuteFilter(source);
                        yPosition = Convert.ToInt16((Convert.ToDecimal(resize.Height) - Convert.ToDecimal(cHeight)) / new Decimal(2));
                    }
                    source = CropImage(source, xPosition, yPosition, cWidth, cHeight);
                    break;
                case ResizeStyle.Normal:
                    resize.KeepAspectRatio = true;
                    //TODO:平铺
                    break;
            }
            //宽度，和高度，必须与之一样
            if (mustFit)
            {
                source = CentreImage(source, width, height, resize.BackGroundColor);
            }
            return source;
        }

        /// <summary>
        /// 将图片放在一个空白的width * height的长方形正中间
        /// </summary>
        /// <param name="source"></param>
        /// <param name="width"></param>
        /// <param name="height"></param>
        /// <returns></returns>
        public static Image CentreImage(Image source, int width, int height, Color backgroundColor)
        {
            Bitmap b = new Bitmap(width, height);
            using (var g = Graphics.FromImage(b))
            {
                int xPosition = 0;
                int yPosition = 0;
                if (width > source.Width)
                {
                    xPosition = Convert.ToInt16(Convert.ToDecimal(width - source.Width) / new Decimal(2));
                }
                if (height > source.Height)
                {
                    yPosition = Convert.ToInt16(Convert.ToDecimal(height - source.Height) / new Decimal(2));
                }
                g.InterpolationMode = InterpolationMode.HighQualityBicubic;
                g.FillRectangle(new SolidBrush(backgroundColor), -1, -1, width + 2, height + 2); //重新画一下背景颜色
                g.DrawImage(source, xPosition, yPosition, source.Width, source.Height);
                g.Save();
                source = (Image)b.Clone();
                b.Dispose();
            }
            return source;
        }


        /// <summary>
        /// 剪切图片
        /// </summary>
        /// <param name="source"></param>
        /// <param name="xPosition"></param>
        /// <param name="yPosition"></param>
        /// <param name="width"></param>
        /// <param name="height"></param>
        public static Image CropImage(Image source, int xPosition, int yPosition, int width, int height)
        {
            Bitmap temp = (Bitmap)source;
            Bitmap bmap = (Bitmap)temp.Clone();
            if (xPosition + width > source.Width)
            {
                width = source.Width - xPosition;
            }
            if (yPosition + height > source.Height)
            {
                height = source.Height - yPosition;
            }
            Rectangle rect = new Rectangle(xPosition, yPosition, width, height);
            source = (Bitmap)bmap.Clone(rect, bmap.PixelFormat);
            bmap.Dispose();
            temp.Dispose();
            return source;
        }


        /// <summary>
        /// 保存Jpeg到文件
        /// </summary>
        /// <param name="path"></param>
        /// <param name="img"></param>
        /// <param name="quality"></param>
        public static void SaveJpeg(string path, Image img, int quality)
        {
            //如果文件已存在，删除文件
            if (File.Exists(path))
            {
                File.Delete(path);
            }
            //如果文件夹不存在，则创建文件夹
            string dir = new FileInfo(path).Directory.FullName;
            if (!Directory.Exists(dir))
            {
                Directory.CreateDirectory(dir);
            }
            img.Save(path, GetEncoderInfo("image/jpeg"), GetJpegParams(quality));
        }
        /// <summary>
        /// 保存Jpeg到内存
        /// </summary>
        /// <param name="img"></param>
        /// <param name="quality"></param>
        /// <returns></returns>
        public static Image SaveJpeg(Image img, int quality)
        {
            Image newImage = null;
            using (MemoryStream s = new MemoryStream())
            {
                Image saveImage = (Image)img.Clone();
                saveImage.Save(s, GetEncoderInfo("image/jpeg"), GetJpegParams(quality));
                newImage = Image.FromStream(s);
            }
            return (Image)newImage.Clone();
        }

        public static EncoderParameters GetJpegParams(int quality)
        {
            if (quality < 0 || quality > 100)
            {
                throw new ArgumentOutOfRangeException("quality must be between 0 and 100.");
            }
            // Encoder parameter for image quality
            EncoderParameter qualityParam = new EncoderParameter(System.Drawing.Imaging.Encoder.Quality, quality);
            // Jpeg image codec
            EncoderParameters encoderParams = new EncoderParameters(1);
            encoderParams.Param[0] = qualityParam;
            return encoderParams;
        }
        /// <summary>
        /// Returns the image codec with the given mime type
        /// </summary>
        private static ImageCodecInfo GetEncoderInfo(string mimeType)
        {
            // Get image codecs for all image formats
            ImageCodecInfo[] codecs = ImageCodecInfo.GetImageEncoders();

            // Find the correct image codec
            for (int i = 0; i < codecs.Length; i++)
                if (codecs[i].MimeType == mimeType)
                    return codecs[i];
            return null;
        }
    }
}
